/*******************************************************************************
 * Copyright (C) 2016, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software is owned and published by:
 * Huada Semiconductor Co., Ltd. ("HDSC").
 *
 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
 *
 * This software contains source code for use with HDSC
 * components. This software is licensed by HDSC to be adapted only
 * for use in systems utilizing HDSC components. HDSC shall not be
 * responsible for misuse or illegal use of this software for devices not
 * supported herein. HDSC is providing this software "AS IS" and will
 * not be responsible for issues arising from incorrect user implementation
 * of the software.
 *
 * Disclaimer:
 * HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
 * REGARDING THE SOFTWARE (INCLUDING ANY ACCOMPANYING WRITTEN MATERIALS),
 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
 * WARRANTY OF NONINFRINGEMENT.
 * HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
 * SAVINGS OR PROFITS,
 * EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
 * FROM, THE SOFTWARE.
 *
 * This software may be replicated in part or whole for the licensed use,
 * with the restriction that this Disclaimer and Copyright notice must be
 * included with each copy of this software, whether used in part or whole,
 * at all times.
 */
/******************************************************************************/
/** \file basic.c
 **
 **
 ******************************************************************************/

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "basic.h"
#include "gpio.h"
#include "lpuart.h"
//#include "crc.h"
#include "flash.h"
#include "sysctrl.h"
#include "string.h"

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/

static void HC32_InitSystemClock(void)
{
    SYSCTRL->RCL_f.TRIM  = SYSCTRL_RCL_TRIM_32p8KHz; 
    SYSCTRL->RCH_f.TRIM   = SYSCTRL_RCH_TRIM_48MHz;
    SYSCTRL->RCH_f.DIV  = 2u;                          /*!< RCH:8MHZ */
    SYSCTRL->CR3 = 0x5A5Au;
    SYSCTRL->CR3 = 0xA5A5u;
    SYSCTRL->CR2 = 0x05u;
}

static void HC32_InitUart(void)
{
    SYSCTRL->PERICLKEN0 |= 0x04u; /*!< LPUART0外设时钟使能 */  
    LPUART0->BRR = 0x9u;
    LPUART0->CR = 0x251u;
    LPUART0->ICR = 0u;
    NVIC_SetPriority(LPUART0_IRQn, IrqLevel3);
    NVIC_EnableIRQ(LPUART0_IRQn);
    
    SYSCTRL->PERICLKEN1_f.PA = 1u;       /*!< GPIOA外设时钟使能 */
    GPIOA->OUT = 0u;
    GPIOA->ADS_f.PIN1 = 0u;
    GPIOA->ADS_f.PIN2 = 0u;
    GPIOA->DIR_f.PIN1 = 1u;
    GPIOA->DIR_f.PIN2 = 0u;
    GPIOA->PU_f.PIN1 = 1u;
    GPIOA->PU_f.PIN2 = 1u;
    GPIOA->AFRL_f.AFSEL1 = 1u;
    GPIOA->AFRL_f.AFSEL2 = 1u;
}

static void HC32_InitCRC(void)
{
}

static void HC32_InitTIM(void)
{
    SYSCTRL->CR3 = 0x5A5Au;
    SYSCTRL->CR3 = 0xA5A5u;
    SYSCTRL->CR1_f.GTIMCFG = 0x01u;
    SYSCTRL->PERICLKEN1 |= 0x4000u;
    BTIM3->CR = 0x60u;           //60    /* 64分频 */
    BTIM3->ARR = 125u;
    BTIM3->CNT = 0u;
    BTIM3->ICR = 0u;
    BTIM3->IER_f.UI = 1u;
    NVIC_SetPriority(BTIM3_4_5_IRQn, IrqLevel2);
    NVIC_EnableIRQ(BTIM3_4_5_IRQn);
    BTIM3->CR_f.CEN = 1u;
}

/**
 *******************************************************************************
 ** \brief CPU外围模块初始化
 **
 ** \param [in] None
 **
 ** \retval None
 **
 ******************************************************************************/
void PreiModule_Init(void)
{
    HC32_InitSystemClock();
    HC32_InitUart();
    HC32_InitCRC();
    HC32_InitTIM();
}

void PreiModule_DeInit(void)
{
    SYSCTRL->PERIRESET0 &= ~SYSCTRL_PERIRESET_LPUART0;
    SYSCTRL->PERIRESET0 |= SYSCTRL_PERIRESET_LPUART0;
    SYSCTRL->PERIRESET1 &= ~(SYSCTRL_PERIRESET_PA /*| SYSCTRL_PERIRESET_GTIM*/);
    SYSCTRL->PERIRESET1 |= SYSCTRL_PERIRESET_PA /*| SYSCTRL_PERIRESET_GTIM*/;
    
    SYSCTRL->PERICLKEN0 &= ~SYSCTRL_PERICLK_LPUART0;
    SYSCTRL->PERICLKEN1 &= ~(SYSCTRL_PERICLK_PA /*| SYSCTRL_PERICLK_GTIM*/);
}

/**
 *******************************************************************************
 ** \brief 定时器中断函数，1ms中断一次，用于监测串口数据接收超时，及帧数据处理超时
 **
 ** \param [out] None
 ** \param [in]  None
 **
 ** \retval None
 **
 ******************************************************************************/
uint16_t Cal_CRC16(const uint8_t* pu8Data, uint32_t u32Len)
{
    uint8_t i;
    uint16_t crc = 0xA28C;        // Initial value
    while(u32Len--)
    {
        crc ^= *pu8Data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x8408;        // 0x8408 = reverse 0x1021
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;                // crc^Xorout
}

/**
 *******************************************************************************
 ** \brief  usart以uart模式轮询发送数据
 **
 ** \param  *u8TxBuff        字节缓存指针
 ** \param  u16Length          缓存数组长度
 **
 ** \retval None
 **
 ******************************************************************************/
void UARTModeSendDataPoll(uint8_t *u8TxBuff, uint16_t u16Length)
{
    uint32_t u32Size = u16Length;
    uint8_t *pu8Data = u8TxBuff;
    
    while(u32Size)
    {
        REG_CLEARBITS(LPUART0->ICR, LPUART_ICR_TC);
        REG_WRITE(LPUART0->DR, *pu8Data);
        pu8Data++;
        u32Size--;
        while(!REG_READBITS(LPUART0->ISR, LPUART_ISR_TC)){;}
    }
    REG_CLEARBITS(LPUART0->ICR, LPUART_ICR_TC);
    
    return;
}

/**
 *******************************************************************************
 ** \brief flash扇区擦除
 **
 ** \param [in] u32SectorAddr     所擦除扇区内的地址
 **
 ** \retval Ok                    擦除成功.
 ** \retval ErrorInvalidParameter FLASH地址无效 
 ** \retval ErrorTimeout          操作超时
 **
 ******************************************************************************/
en_result_t Flash_EraseSector(uint32_t u32Addr)
{
    en_result_t enRet = Ok;

    if (u32Addr > (FLASH_BASE_ADDRESS + FLASH_SIZE))    //判断地址有效性
    {
        return ErrorInvalidParameter;
    }

    if ((u32Addr % 4) != 0)
    {
        u32Addr = (u32Addr / FLASH_SECTOR_SIZE) * FLASH_SECTOR_SIZE;
    }
    
    FLASH_SectorErase(u32Addr);

    return enRet;
}

/**
 *******************************************************************************
 ** \brief  flash写数据
 **
 ** \param  u32Addr           写flash首地址
 ** \param  *pu8WriteBuff     数据缓存指针
 ** \param  u32ByteLength     数据长度
 **
 ** \retval Ok                成功
 ** \retval ErrorTimeout     超时错误
 **
 ******************************************************************************/
en_result_t Flash_WriteBytes(uint32_t u32Addr, const uint8_t *pu8WriteBuff, uint32_t u32ByteLength)
{
    en_result_t enRet = Ok;
    
    FLASH_WriteByte(u32Addr, (uint8_t *)pu8WriteBuff, u32ByteLength);
    
    return enRet;
}

/**
 *******************************************************************************
 ** \brief  flash读数据
 **
 ** \param  u32Addr           读首地址
 ** \param  *pu8ReadBuff      数据缓存指针
 ** \param  u32ByteLength     数据长度
 **
 ** \retval None
 **
 ******************************************************************************/
void Flash_ReadBytes(uint32_t u32Addr, uint8_t *pu8ReadBuff, uint32_t u32ByteLength)
{
    memcpy((void *)((uint8_t *)u32Addr), pu8ReadBuff, u32ByteLength);
}

__WEAK uint32_t Sysctrl_GetPClkFreq(void)
{
    return 0;
}
__WEAK void SYSCTRL_PeriphReset(uint32_t u32PeriphReset)
{
    return;
}
/******************************************************************************
 * EOF (not truncated)
 *****************************************************************************/
